<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>图片管理系统</title>
  <link rel="stylesheet" href="https://unpkg.com/element-ui@2.15.13/lib/theme-chalk/index.css">
  <style>
    :root {
      --grid-gap: 18px;
      --preview-max-width: 90vw;
      --preview-max-height: 70vh;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 20px;
    }

    .image-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
      gap: var(--grid-gap);
      margin-top: 24px;
    }

    .image-item {
      position: relative;
      overflow: hidden;
      border-radius: 8px;
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
      background: #f8f9fa;
      transition: transform 0.3s ease;
    }

    .image-item:hover {
      transform: translateY(-5px);
    }

    .image-container {
      width: 100%;
      height: 220px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .image-preview {
      max-width: 100%;
      max-height: 100%;
      object-fit: cover;
      border-radius: 4px;
      opacity: 0;
      transition: opacity 0.3s ease;
    }

    .image-preview.loaded {
      opacity: 1;
    }

    .image-caption {
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      background: linear-gradient(to top, rgba(0,0,0,0.7), rgba(0,0,0,0.3));
      padding: 10px;
      color: white;
      font-size: 0.9em;
    }

    .filename {
      font-size: 0.85em;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      margin: 0;
    }

    .time-ago {
      position: absolute;
      top: 8px;
      right: 8px;
      background: rgba(0,0,0,0.6);
      color: white;
      padding: 4px 8px;
      border-radius: 4px;
      font-size: 0.7em;
    }

    /* 预览对话框样式 */
    .image-preview-dialog {
      display: flex;
      justify-content: center;
      align-items: center;
      width: var(--preview-max-width);
      height: var(--preview-max-height);
      max-width: 1200px;
      max-height: 800px;
      overflow: hidden;
      background: #1a1a1a;
    }

    .preview-container {
      position: relative;
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      background: rgba(0,0,0,0.9);
    }

    .preview-image {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
      transition: transform 0.3s ease;
      cursor: zoom-in;
      border-radius: 8px;
    }

    .preview-image:hover {
      transform: scale(1.02);
    }

    /* 懒加载占位符 */
    .lazy-placeholder {
      width: 100%;
      height: 220px;
      background: #eee;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #999;
      font-size: 0.7em;
    }
  </style>
</head>
<body>
  <div id="app" class="container">
    <!-- 上传区域 -->
    <div class="upload-section">
      <el-upload
        class="el-upload-demo"
        drag
        action="/api/upload"
        :before-upload="beforeUpload"
        :on-success="handleSuccess"
        :on-error="handleError"
        :file-list="[]"
        multiple>
        <i class="el-icon-upload el-icon--large"></i>
        <div class="el-upload__text">拖拽图片到此处或点击上传</div>
        <template #tip>
          <div class="el-upload__tip" style="color:#f56c6c">
            支持 JPG/PNG/GIF，最大 5MB
          </div>
        </template>
      </el-upload>
    </div>

    <!-- 图片列表 -->
    <div class="image-grid" v-loading="loading">
      <div class="empty-state" v-if="!loading && images.length === 0">
        <i class="el-icon-picture-outline"></i>
        <p>暂无图片，点击上方区域上传</p>
      </div>

      {% raw %}
      <div
        v-for="(img, index) in images"
        :key="img.filename"
        class="image-item"
        @click="handlePreview(img.url)"
      >
        <div class="image-container">
          <!-- 懒加载实现 -->
          <img
            v-if="isVisible(index)"
            :src="img.url"
            class="image-preview loaded"
            @load="imageLoaded(index)"
          >
          <div v-else class="lazy-placeholder">加载中...</div>
        </div>
        <div class="image-caption">
          <span class="filename">${ img.filename }</span>
        </div>
        <div class="time-ago">${ formatTime(img.upload_time) }</div>
      </div>
      {% endraw %}
    </div>

    <!-- 图片预览 -->
    <el-dialog
      :visible.sync="previewVisible"
      :fullscreen="true"
      :before-close="handleClose"
      custom-class="image-preview-dialog"
    >
      <div class="preview-container">
        <img
          :src="previewImage"
          class="preview-image"
          @load="previewLoaded"
        >
      </div>
    </el-dialog>
  </div>

  <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
  <script src="https://unpkg.com/element-ui@2.15.13/lib/index.js"></script>
  <script>
    new Vue({
      el: '#app',
      delimiters: ['${', '}'],
      data() {
        return {
          images: [],
          loading: true,
          previewVisible: false,
          previewImage: '',
          observer: null,
          visibleItems: new Set()
        };
      },
      created() {
        this.loadImages();
        this.initIntersectionObserver();
        setInterval(() => this.loadImages(), 10000);
      },
      methods: {
        // 图片加载控制
        isVisible(index) {
          return true
        },
        imageLoaded(index) {
          this.visibleItems.add(index);
        },
        initIntersectionObserver() {
          this.observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
              if (entry.isIntersecting) {
                const index = entry.target.dataset.index;
                this.$set(this.visibleItems, index, true);
                this.observer.unobserve(entry.target);
              }
            });
          }, {
            rootMargin: '0px',
            threshold: 0.1
          });

          document.querySelectorAll('.image-item').forEach((el, index) => {
            el.dataset.index = index;
            this.observer.observe(el);
          });
        },

        // 预览控制
        handlePreview(url) {
          this.previewImage = url;
          this.previewVisible = true;
        },
        handleClose(done) {
          this.previewImage = '';
          this.previewVisible = false;
          done();
        },
        previewLoaded() {
          console.log('预览图片加载完成');
        },

        // 图片加载
        async loadImages() {
          try {
            this.loading = true;
            const res = await fetch('/api/images');
            this.images = await res.json();
          } catch (error) {
            this.$message.error('加载图片失败');
          } finally {
            this.loading = false;
          }
        },
        beforeUpload(file) {
          const isImage = ['image/jpeg', 'image/png', 'image/gif'].includes(file.type);
          const isLt5M = file.size / 1024 / 1024 < 5;

          if (!isImage) {
            this.$message.error('仅支持 JPG/PNG/GIF 格式');
            return false;
          }
          if (!isLt5M) {
            this.$message.error('图片大小不能超过 5MB');
            return false;
          }
          return true;
        },
        formatTime(timestamp) {
          const date = new Date(timestamp);
          return date.toLocaleString('zh-CN', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
          });
        }
      }
    });
  </script>
</body>
</html>